/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#ifndef _INC_AK_TYPES_
#define	_INC_AK_TYPES_

#ifdef __cplusplus
extern "C" {
#endif

/* Target CPU Define */
#define 	_CPU_X86_32		0X00010001
#define 	_CPU_X86_64		0X00010002
#define 	_CPU_ARM_32		0X00020001
#define 	_CPU_ARM_64		0X00020002
#define 	_CPU_PPC_32		0X00030001
#define 	_CPU_PPC_64		0X00030002
#define 	_CPU_MIPS_32	0X00040001
#define 	_CPU_MIPS_64	0X00040002

/* Target OS Define */
#define 	_OS_GNU			0X00050001
#define 	_OS_WIN			0X00050002

/* User Should Define Target */
#ifndef  	_TARGET_CPU
#define 	_TARGET_CPU  	_CPU_X86_64
#endif
#ifndef  	_TARGET_OS
#define 	_TARGET_OS		_OS_GNU
#endif

/* Header Files Define */
/* Linux */
#if 	_TARGET_OS == _OS_GNU
#ifndef	_GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <malloc.h>
#include <fcntl.h>
#include <signal.h>

#ifndef __USE_UNIX98
#define __USE_UNIX98
#endif
#include <pthread.h>
	
#include <sys/time.h>

/* Windows */
#elif 	_TARGET_OS == _OS_WIN
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <malloc.h>
#include <process.h>

/* In Order to Co-Work with DDK */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT  	0x0600
#endif

#ifndef  WSA_VERSION
#define	 WSA_VERSION  	MAKEWORD(2,0)
#include "winsock2.h"
#endif

#include <windows.h>

#endif

/*	---------------------------------------------------------------------------
**	We use the Marcos to define the functions' return & BOOL -1, 0, 1 Value.
*/
#define _B_TRUE 	1
#define _B_FALSE 	0

#define _E_SUCC 	0
#define _E_FAIL 	(-1)

#define _F_YES		1
#define _F_NO 		0
#define _F_UNK		(-1)


/* ---------------------------------------------------------------------------
** Basic Value Type. We Strong Advice just Using the Basic Type. 
** Cautions:	On 32-Bit System, sizeof(long) = 4, 	On 64-Bit System, sizeof(long) = 8
*/
typedef 	char 					sInt8;
typedef 	unsigned char			uInt8;
typedef 	short					sInt16;
typedef 	unsigned short			uInt16;
typedef 	int						sInt32;
typedef 	unsigned int			uInt32;
typedef 	unsigned long long		uInt64;
typedef 	long long				sInt64;

typedef 	long					sLong;		
typedef 	unsigned long			uLong;


/* ---------------------------------------------------------------------------
**	Alignment.
*/
/* Linux */
#if 	_TARGET_OS == _OS_GNU
#define _OS_ALIGN(val) 	__attribute__((aligned(val)))
/* Windows */
#elif 	_TARGET_OS == _OS_WIN
#define _OS_ALIGN(val) 	__declspec(align(val))
#else
#define _OS_ALIGN(val)
#endif


/*  ---------------------------------------------------------------------------
**  String Operations
**  On Linux : 
**  	The functions snprintf() and vsnprintf() do not write more than size bytes (including the trailing '\0'). 
**  	If the output was truncated due to this limit then the return value is the number of characters (not including the trailing '\0')
** 	which would have been written to the final string if enough space had been available. 
** 	Thus, a return value of size or more means that the output was truncated. (See also below under NOTES.) If an output error is encountered, a negative value is returned. 
** On Windows:
**	If len < count, then len characters are stored in buffer, a null-terminator is appended, and len is returned.
**	If len = count, then len characters are stored in buffer, no null-terminator is appended, and len is returned.
**	If len > count, then count characters are stored in buffer, no null-terminator is appended, and a negative value is returned. 
*/
#define SYS_STRLEN 		strlen
#define SYS_STRCMP 		strcmp
#define SYS_STRCHR		strchr
#define SYS_STRSTR		strstr
#define SYS_STRDUP 		strdup
#define SYS_STRTOL 		strtol
#define SYS_STRNCMP		strncmp

#define SYS_ATOI(val) 	atoi((char *)(val))

/* Linux */
#if 	_TARGET_OS == _OS_GNU
#define SYS_STRCMPI		strcasecmp
#define SYS_STRSTRI 	strcasestr
#define SYS_STRNCMPI	strncasecmp

#define	SYS_PRINTF		printf
#define	SYS_SSCANF		sscanf

#define	SYS_STRNCPY(strDst, strSize, strSrc, strCnt)		strncpy(strDst, strSrc, strCnt)
#define	SYS_SNPRINTF	snprintf
#define	SYS_VSNPRINTF	vsnprintf

/* Windows */
#elif 	_TARGET_OS == _OS_WIN
/* Be Careful if Use Borland C++, Different Variable-Len Marco Parameter. */
#ifdef 	_BORLAND_
#define SYS_STRCMPI		stricmp
#define SYS_STRNCMPI	strnicmp
#define	SYS_PRINTF		printf
#define	SYS_SSCANF		sscanf

#define	SYS_STRNCPY(strDst, strSize, strSrc, strCnt)		strncpy(strDst, strSrc, strCnt)
#define	SYS_SNPRINTF 	_snprintf
#define	SYS_VSNPRINTF	_vsnprintf

/* For M$ CRT's Security */
#else
#define SYS_STRCMPI		_stricmp
#define SYS_STRNCMPI	_strnicmp

#define	SYS_PRINTF		printf_s
#define	SYS_SSCANF		sscanf_s

#define	SYS_STRNCPY(strDst, strSize, strSrc, strCnt)	strncpy_s(strDst, strSize, strSrc, strCnt)
#define	SYS_SNPRINTF(buf, len, format,...)				_snprintf_s(buf, len, len, format, ##__VA_ARGS__)
#define	SYS_VSNPRINTF(buf, len, format,...)				vsnprintf_s(buf, len, len, format, ##__VA_ARGS__)
#endif
#endif

/*  ---------------------------------------------------------------------------
**  File Ops : the No-Lock Flush is not Thread-Safe. Using if U want Performance and be Sure.
*/
#define SYS_CLOSE(funcClose, vFd) \
do{\
	if((vFd) != -1){\
		funcClose(vFd); vFd = -1;\
	}\
}while(0)
	
/* Linux */
#if 	_TARGET_OS == _OS_GNU
#define	SYS_FOPEN(fd, fname, fmode) 	(fd = fopen(fname, fmode))
#define	SYS_FPRINTF		fprintf
#define	SYS_FFLUSH		fflush_unlocked
/* Windows */
#elif 	_TARGET_OS == _OS_WIN
#define	SYS_FOPEN(fd, fname, fmode) 	(fopen_s(&(fd), fname, fmode))
#define	SYS_FPRINTF		fprintf_s
#define	SYS_FFLUSH		_fflush_nolock
#endif


/*  ---------------------------------------------------------------------------
**  CallBack Ops
*/
/* Linux */
#if 	_TARGET_OS == _OS_GNU
#define SYS_CALLBACK 	 
typedef void *				_t_sysHandle;
typedef pthread_t 			_t_sysThread;

/* Windows */
#elif 	_TARGET_OS == _OS_WIN
#define SYS_CALLBACK 		CALLBACK 
typedef HANDLE				_t_sysHandle;
typedef HANDLE 				_t_sysThread;

#endif


/* ---------------------------------------------------------------------------
**	Basic Calc Marco
*/
#define 	SYS_MAX(a,b)		((a) > (b) ? (a) : (b))
#define 	SYS_MIN(a,b)		((a) < (b) ? (a) : (b))

/* Calc the Array's Element Size */
#define 	_N_ARRAY(vArray) 				(sizeof(vArray)/sizeof(vArray[0]))
#define 	_I_ARRAY(vArray, vElem) 		((vElem) - (vArray))

/* Calc the Element Offset in the Structure  */
#define 	_O_ELEMENT(type, elem)			(unsigned long)(&(((type*)0)->elem))
#define 	_S_ELEMENT(type, elem)			sizeof((((type*)0)->elem))

#define 	_O_PARENT(type, elem, pAddr)	(type *)((unsigned char *)(pAddr) - _O_ELEMENT(type, elem))


/* ---------------------------------------------------------------------------
**	Memory OP Functions & Marcos:
*/
#define SYS_MEMCHR 						memchr
#define SYS_MEMCMP 						memcmp
#define SYS_MEMCPY(dst, src, len) 		memcpy((void *)(dst), (void *)(src), (len))
#define SYS_REALLOC						realloc
#define SYS_MALLOC						malloc
#define SYS_CALLOC						calloc
#define SYS_MEMSET						memset
#define SYS_MEMZERO(ptr, size)			memset((void *)(ptr), 0, size)

#define SYS_STRNLEN						strnlen

#if 	_TARGET_OS == _OS_GNU
/* Linux */
#define SYS_ALIGN_ALLOC(vAlign, vSize) 	memalign(vAlign, vSize)
#define SYS_ALIGN_FREE(vPtr)				free(vPtr)
/* Windows */
#elif 	_TARGET_OS == _OS_WIN
#define SYS_ALIGN_ALLOC(vAlign, vSize)		_aligned_malloc(vSize, vAlign)
#define SYS_ALIGN_FREE(vPtr)				_aligned_free(vPtr)
#endif

#define SYS_FREE(vPtr)	\
do{\
	if(vPtr){\
		free(vPtr); \
		(vPtr) = NULL;\
	}\
}while(0)

	
/* ---------------------------------------------------------------------------
**	Trace Type & Define :
*/
#define 	TRACELVL_FATAL 		1
#define		TRACELVL_ERROR 		2
#define		TRACELVL_WARNING	5
#define		TRACELVL_NORMAL		10
#define		TRACELVL_DEBUG		20
#define		TRACELVL_ALL		30

#ifdef 	_BORLAND_
#define 	SYS_TRACE(sLvl, uLvl, pucFormat...) 	\
do{\
	if(uLvl <= sLvl){\
		STrace_Printf(__FUNC__, __LINE__, pucFormat, __VA_ARGS__);}\
}while(0)

#else
#define 	SYS_TRACE(sLvl, uLvl, pucFormat,...) 	\
do{\
	if(uLvl <= sLvl){\
		STrace_Printf(__FUNCTION__, __LINE__, pucFormat, ##__VA_ARGS__);}\
}while(0)

#define 	SYS_TRACEx(sLvl, uLvl, pucFormat,...) 	\
	do{\
		if(uLvl <= sLvl){\
			STrace_PrintfEx(pucFormat, ##__VA_ARGS__);}\
	}while(0)
#endif

extern	void STrace_Switch(int flag);

extern 	void STrace_Printf(const char * funcN, int lineNo, char * pucFormat, ...);
extern	void STrace_PrintfEx(char * pucFormat, ...);
extern	void STrace_HexDump(unsigned char * pBuf, unsigned int lBuf);

/* ---------------------------------------------------------------------------
**	Sleep Ops:
**	On Linux: 
**		Compared to sleep(3) and usleep(3), nanosleep() has the advantage of not affecting any signals, it is standardized by POSIX,
**		it provides higher timing resolution, and it allows to continue a sleep that has been interrupted by a signal more easily. 	
**	EINTR
**	    	The pause has been interrupted by a non-blocked signal that was delivered to the process. 
**		The remaining sleep time has been written into *rem so that the process can easily call nanosleep() again and continue with the pause. 
**
**	On Windows:
**	The time interval for which execution is to be suspended, in milliseconds.
**	A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. ?? Not Equal = SwitchToThread() ??
**	If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.
**	A value of INFINITE indicates that the suspension should not time out.
*/
#if 	_TARGET_OS == _OS_GNU
#include <sched.h>
static	void	__inline	SYS_SLEEP(int ms)
{
	struct timespec vTs;
	/* Fast Path */
	if(ms > 0){
		vTs.tv_sec = (ms/1000);
		vTs.tv_nsec= (ms%1000) * 1000000;
		while(nanosleep(&vTs, &vTs) == -1)
			continue;
		return;
	}else if(ms == 0){
		sched_yield();	
		return;
	}
	/* Slow Path */
	else{
		ms = 0X7FFFFFFF;
		vTs.tv_sec = (ms/1000);
		vTs.tv_nsec= (ms%1000) * 1000000;
		while(nanosleep(&vTs, &vTs) == -1)
			continue;
		return;
	}
}
/* Windows */
#elif 	_TARGET_OS == _OS_WIN
#define SYS_SLEEP(ms) 			Sleep(ms)
#endif		


/* ---------------------------------------------------------------------------
** Common CallBack Entry.
*/
typedef struct _t_cbentry{
	int (*	cbProc)();
	void *	pArg;
	long 	lArg;		/* On 64Bit OS, will be 8-Bytes */
}_t_cbentry;

#define _CBENTRY_CLEAR(vDst) \
do{\
	(vDst)->cbProc  = NULL; 	\
	(vDst)->pArg  = NULL; 		\
	(vDst)->lArg  = 0; 			\
}while(0)

#define _CBENTRY_INIT(vEntry, vCbProc, vPCbArg, vVCbArg) \
do{\
	(vEntry)->cbProc  = (int (*)())vCbProc; \
	(vEntry)->pArg  = (void *)vPCbArg;	\
	(vEntry)->lArg  = (long	)vVCbArg; 	\
}while(0)

#define _CBENTRY_ASSIGN(vDst, vSrc) \
do{\
	(vDst)->cbProc  = (vSrc)->cbProc; 	\
	(vDst)->pArg  = (vSrc)->pArg; 		\
	(vDst)->lArg  = (vSrc)->lArg; 		\
}while(0)

#define _CBENTRY_EXEC(pCbEntry) \
do{\
	if((pCbEntry) && (pCbEntry)->cbProc){\
		(pCbEntry)->cbProc((pCbEntry)->pArg, (pCbEntry)->lArg);\
	}\
}while(0)


/* ---------------------------------------------------------------------------
** Common Object Hint:
*/
typedef struct _t_objhint{
	void 	* 			pObj;
	unsigned long 		tagId;
	unsigned long 		casId;
}_t_objhint;

#define SYS_OBJHINT_CLEAR(vHint) 	\
do{\
	(vHint)->pObj 	= NULL;		\
	(vHint)->casId	= 0;			\
	(vHint)->tagId	= 0;			\
}while(0)

#define SYS_OBJHINT_INIT(vHint, vObj, vCasId) 	\
do{\
	(vHint)->pObj 	= (void *)(vObj);		\
	(vHint)->casId	= (long)(vCasId);		\
	(vHint)->tagId	= 0;						\
}while(0)

#define SYS_OBJHINT_ASSIGN(vDst, vSrc) 		\
do{\
	(vDst)->pObj 	= (vSrc)->pObj;		\
	(vDst)->casId	= (vSrc)->casId;	\
	(vDst)->tagId	= (vSrc)->tagId;	\
}while(0)

#define SYS_T_CAST(type, object) 	((type)object)


/* ---------------------------------------------------------------------------
**	Special OP, Static Cycle for(;;) Opti? :
*/
#define 	FAST_EX4_OP(iter, count, opera)\
do{\
	iter = (count) >> 2;\
	while(iter--){	\
		opera;			opera;		\
		opera;			opera;		\
	};\
	iter = (count) & 0X03;\
	while(iter--){	\
		opera;		\
	};\
}while(0)

#define 	FAST_EX8_OP(iter, count, opera)\
do{\
	iter = (count) >> 3;\
	while(iter--){	\
		opera;			opera;			\
		opera;			opera;			\
		opera;			opera;			\
		opera;			opera;			\
	};\
	iter = (count) & 0X4;\
	if(iter){	\
		opera;			opera;			\
		opera;			opera;			\
	};\
	iter = (count) & 0X3;	\
	while(iter--){		\
		opera;			\
	};\
}while(0)


/* Some Mod Func */
#define 	SYS_MOD8K(var)		((var) & 0X1FFF)
#define 	SYS_MOD4K(var)		((var) & 0XFFF)
#define 	SYS_MOD2K(var)		((var) & 0X7FF)
#define 	SYS_MOD1K(var)		((var) & 0X3FF)
#define 	SYS_MOD512(var)		((var) & 0X1FF)
#define 	SYS_MOD256(var) 	((var) & 0XFF)
#define 	SYS_MOD128(var) 	((var) & 0X7F)
	
/* Some Dist Func */
#define 	SYS_DIST8K(snCurr, snRef)	(SYS_MOD8K(0X2000+(snCurr)-(snRef)))
#define 	SYS_DIST4K(snCurr, snRef)	(SYS_MOD4K(0X1000+(snCurr)-(snRef)))
#define 	SYS_DIST2K(snCurr, snRef)	(SYS_MOD2K(0X0800+(snCurr)-(snRef)))
#define 	SYS_DIST1K(snCurr, snRef)	(SYS_MOD1K(0X0400+(snCurr)-(snRef)))
#define 	SYS_DIST512(snCurr, snRef)	(SYS_MOD512(0X200+(snCurr)-(snRef)))
#define 	SYS_DIST256(snCurr, snRef)	(SYS_MOD256(0X100+(snCurr)-(snRef)))
#define 	SYS_DIST128(snCurr, snRef)	(SYS_MOD128(0X080+(snCurr)-(snRef)))
	
#define 	SYS_VALID(exprC, exprH, exprE)\
do{ \
	if(exprC){\
		exprH;\
	}else{\
		exprE;\
	}\
}while(0)


/* Message Element Define */
typedef struct _t_sysMsgElem{
	unsigned int		type	:	16, 	/* Application Custom/Parse field, for message dispatch */
						dir 	:	2,		/* Indicate Request/Response, Just a Reference. */
						reserv	:	14; 	/* Reserved */
	unsigned int		length; 			/* Length of the whole element */
	unsigned long long	piggyback;			/* For Piggy back Message */
}_t_sysMsgElem;
	
#define _MSGELEM_REQ 	0X00 				/* Message is Request */
#define _MSGELEM_RSP 	0X01 				/* Message is Response */


/* Use the Call Stack */			
#define _SYS_STACK_MAX 		0X3F			
#define _SYS_FUNCS_MAX 		0XFF			
typedef struct{
	int 	line;
	char 	func[_SYS_FUNCS_MAX + 1];
}_t_sys_call_stack;


/* Use the Push & Pop */			
typedef struct{
	int 					lvl;
	int 					shadow;
	void 				 * 	pVoid;
	_t_sys_call_stack 		stack[_SYS_STACK_MAX + 1];
}_t_sys_call_cookie;

#define SYS_CALLSTK_INIT(pCookie) \
	do{\
			(pCookie)->lvl 		= 0;\
			(pCookie)->shadow 	= 0;\
			(pCookie)->pVoid 	= NULL;\
	}while(0)

#define SYS_CALLSTK_PUSH(pCookie) \
	do{\
		if(pCookie){\
			if((pCookie)->shadow >= 0){	\
				(pCookie)->shadow += 1; \
				if((pCookie)->lvl < _SYS_STACK_MAX){	\
					(pCookie)->stack[(pCookie)->lvl].line = __LINE__;	\
					SYS_SNPRINTF((pCookie)->stack[(pCookie)->lvl].func, _SYS_FUNCS_MAX, "%s", __FUNCTION__);\
					(pCookie)->lvl += 1;\
				}\
			}\
		}\
	}while(0)

#define SYS_CALLSTK_POP(pCookie) \
	do{\
		if(pCookie){\
			if((pCookie)->shadow > 0){	\
				(pCookie)->shadow -= 1; \
				if((pCookie)->shadow <= _SYS_STACK_MAX){\
					(pCookie)->lvl -= 1;\
				}\
			}\
		}\
	}while(0)

extern	void	SCallStk_Dump(_t_sys_call_cookie * pCookie);


#ifdef __cplusplus
}
#endif

#endif



